// 探索盒子如何让我们在没有太多干扰的情况下定义递归数据类型。

use crate::List::{Cons, Nil};

enum List {
    Cons(i32, Box<List>),
    Nil,
}

pub fn main() {
    let list = Cons(1, Cons(2, Cons(3, Nil)));
}

// 第一个Cons值成立1，另一个List值成立。这个List值是
// 另一个Cons值，也是2另一个List值。这个List值是另一个Cons
// 持有的值3和一个List值，它是 finally Nil，
// 表示列表结束的非递归变体。

// 因为 aBox<T>是一个指针，
// Rust 总是知道 a 需要多少空间Box<T> 
// ：指针的大小不会根据它指向的数据量而改变。
// 这意味着我们可以将 aBox<T>放入Cons变量中，
// 而不是List直接放入另一个值。
// 将Box<T>指向List 将在堆上而不是在Cons变体内部的下一个值。
// 从概念上讲，我们仍然有一个列表，它是由包含其他列表的列表创建的，
// 但是这种实现现在更像是将项目彼此相邻而不是彼此放在一起。

pub fn main0() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}

// 盒子只提供间接和堆分配；
// 它们没有任何其他特殊功能，
// 就像我们将在其他智能指针类型中看到的那样。
// 它们也没有这些特殊功能引起的性能开销，
// 因此它们在诸如 cons 列表之类的情况下很有用，
// 其中间接是我们需要的唯一功能。我们还将在第 17 章中看到更多有关盒子的用例。

